<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>I2C数据读取数组赋值演示</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#3B82F6',
                        secondary: '#10B981',
                        accent: '#F59E0B',
                        dark: '#1E293B',
                        light: '#F8FAFC'
                    }
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .array-item {
                @apply border border-gray-300 rounded p-3 text-center transition-all duration-300;
            }
            .array-item-active {
                @apply border-primary bg-blue-50 transform scale-105;
            }
            .mpu-register {
                @apply bg-gray-100 border border-gray-300 rounded p-2 text-center text-sm;
            }
            .data-flow {
                @apply absolute h-2 bg-primary rounded-full animate-pulse;
            }
            .code-highlight {
                @apply bg-yellow-100 px-1 rounded;
            }
        }
    </style>
</head>
<body class="bg-gray-50 min-h-screen font-sans">
    <header class="bg-primary text-white shadow-md">
        <div class="container mx-auto px-4 py-4">
            <h1 class="text-2xl font-bold">I2C数据读取与数组赋值演示</h1>
        </div>
    </header>

    <main class="container mx-auto px-4 py-8">
        <section class="bg-white rounded-lg shadow-md p-6 mb-8">
            <h2 class="text-xl font-semibold mb-4 text-dark">函数工作原理说明</h2>
            <p class="mb-4 text-gray-700">
                在你的代码中，<code class="bg-gray-100 px-1 py-0.5 rounded">HAL_I2C_Mem_Read</code> 函数内部已经实现了数据读取和数组赋值的逻辑。当你传递数组指针给这个函数时：
            </p>
            <ol class="list-decimal list-inside mb-6 pl-4 space-y-2 text-gray-700">
                <li>函数通过I2C总线从MPU6050读取指定数量的数据字节</li>
                <li>函数使用你提供的数组指针，直接将读取到的数据存储到数组的各个位置</li>
                <li>由于数组是通过指针传递的，函数执行完毕后，你的原始数组已经包含了新的数据</li>
            </ol>
            
            <div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
                <pre class="text-sm overflow-x-auto"><code>// 你的代码中数组会被自动赋值
void Inf_MPU6050_ReadRegs(uint8_t startReg, uint8_t *bytes, uint8_t len)
{
    // HAL_I2C_Mem_Read函数内部会填充bytes数组
    HAL_I2C_Mem_Read(&hi2c1,
                     MPU6050_ADDR_R,
                     startReg,
                     I2C_MEMADD_SIZE_8BIT,
                     <span class="code-highlight">bytes</span>,  // 数组指针
                     <span class="code-highlight">len</span>,     // 要读取的长度
                     2000);
}</code></pre>
            </div>
        </section>

        <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
            <!-- MPU6050寄存器 -->
            <section>
                <div class="bg-white rounded-lg shadow-md p-6 h-full">
                    <h2 class="text-xl font-semibold mb-6 text-dark flex items-center">
                        <i class="fa fa-microchip text-accent mr-2"></i>MPU6050 寄存器
                    </h2>
                    
                    <div class="mb-4">
                        <div class="text-center text-sm text-gray-500 mb-2">陀螺仪数据寄存器 (0x43-0x48)</div>
                        <div class="grid grid-cols-2 gap-3" id="mpuRegisters">
                            <div class="mpu-register" data-reg="0x43">
                                <div class="font-medium">GYRO_XOUT_H</div>
                                <div class="text-xs text-gray-500">0x43</div>
                                <div class="mt-1 text-primary font-medium">0x3C</div>
                            </div>
                            <div class="mpu-register" data-reg="0x44">
                                <div class="font-medium">GYRO_XOUT_L</div>
                                <div class="text-xs text-gray-500">0x44</div>
                                <div class="mt-1 text-primary font-medium">0xAB</div>
                            </div>
                            <div class="mpu-register" data-reg="0x45">
                                <div class="font-medium">GYRO_YOUT_H</div>
                                <div class="text-xs text-gray-500">0x45</div>
                                <div class="mt-1 text-primary font-medium">0x12</div>
                            </div>
                            <div class="mpu-register" data-reg="0x46">
                                <div class="font-medium">GYRO_YOUT_L</div>
                                <div class="text-xs text-gray-500">0x46</div>
                                <div class="mt-1 text-primary font-medium">0x78</div>
                            </div>
                            <div class="mpu-register" data-reg="0x47">
                                <div class="font-medium">GYRO_ZOUT_H</div>
                                <div class="text-xs text-gray-500">0x47</div>
                                <div class="mt-1 text-primary font-medium">0x56</div>
                            </div>
                            <div class="mpu-register" data-reg="0x48">
                                <div class="font-medium">GYRO_ZOUT_L</div>
                                <div class="text-xs text-gray-500">0x48</div>
                                <div class="mt-1 text-primary font-medium">0xF2</div>
                            </div>
                        </div>
                    </div>
                    
                    <div class="text-center">
                        <button id="startDemoBtn" class="bg-accent hover:bg-amber-600 text-white px-6 py-2 rounded-lg shadow-md transition flex items-center mx-auto">
                            <i class="fa fa-play mr-2"></i>开始演示
                        </button>
                    </div>
                </div>
            </section>
            
            <!-- 数据传输过程 -->
            <section>
                <div class="bg-white rounded-lg shadow-md p-6 h-full">
                    <h2 class="text-xl font-semibold mb-6 text-dark flex items-center">
                        <i class="fa fa-exchange text-primary mr-2"></i>数据传输过程
                    </h2>
                    
                    <div class="relative h-64 flex items-center justify-center">
                        <div class="absolute left-1/4 top-1/2 transform -translate-x-1/2 -translate-y-1/2 w-20 h-20 bg-gray-100 rounded-full flex items-center justify-center border-2 border-gray-300">
                            <span class="text-sm font-medium">MPU6050</span>
                        </div>
                        
                        <div class="absolute right-1/4 top-1/2 transform -translate-x-1/2 -translate-y-1/2 w-20 h-20 bg-gray-100 rounded-full flex items-center justify-center border-2 border-gray-300">
                            <span class="text-sm font-medium">MCU</span>
                        </div>
                        
                        <div class="data-flow hidden absolute left-[35%] right-[35%] top-1/2 transform -translate-y-1/2"></div>
                        
                        <div id="transferSteps" class="absolute bottom-0 left-0 right-0 text-center text-sm text-gray-500">
                            点击"开始演示"观看数据传输过程
                        </div>
                    </div>
                    
                    <div class="mt-6">
                        <h3 class="font-medium text-gray-700 mb-2 border-b pb-1">函数调用参数</h3>
                        <div class="space-y-2 text-sm">
                            <div class="flex justify-between">
                                <span class="text-gray-600">I2C句柄:</span>
                                <span class="font-medium">&hi2c1</span>
                            </div>
                            <div class="flex justify-between">
                                <span class="text-gray-600">设备地址:</span>
                                <span class="font-medium">MPU6050_ADDR_R (0xD1)</span>
                            </div>
                            <div class="flex justify-between">
                                <span class="text-gray-600">起始寄存器:</span>
                                <span class="font-medium">MPU_GYRO_XOUTH_REG (0x43)</span>
                            </div>
                            <div class="flex justify-between">
                                <span class="text-gray-600">数据长度:</span>
                                <span class="font-medium">6 字节</span>
                            </div>
                            <div class="flex justify-between">
                                <span class="text-gray-600">目标数组:</span>
                                <span class="font-medium code-highlight">data[6]</span>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
            
            <!-- 数组变化 -->
            <section>
                <div class="bg-white rounded-lg shadow-md p-6 h-full">
                    <h2 class="text-xl font-semibold mb-6 text-dark flex items-center">
                        <i class="fa fa-list-ol text-secondary mr-2"></i>数组数据变化
                    </h2>
                    
                    <div class="mb-6">
                        <div class="text-center text-sm text-gray-500 mb-3">data[6] 数组</div>
                        <div class="grid grid-cols-3 gap-2" id="arrayContainer">
                            <div class="array-item">
                                <div class="text-xs text-gray-500">data[0]</div>
                                <div class="font-medium">0x00</div>
                            </div>
                            <div class="array-item">
                                <div class="text-xs text-gray-500">data[1]</div>
                                <div class="font-medium">0x00</div>
                            </div>
                            <div class="array-item">
                                <div class="text-xs text-gray-500">data[2]</div>
                                <div class="font-medium">0x00</div>
                            </div>
                            <div class="array-item">
                                <div class="text-xs text-gray-500">data[3]</div>
                                <div class="font-medium">0x00</div>
                            </div>
                            <div class="array-item">
                                <div class="text-xs text-gray-500">data[4]</div>
                                <div class="font-medium">0x00</div>
                            </div>
                            <div class="array-item">
                                <div class="text-xs text-gray-500">data[5]</div>
                                <div class="font-medium">0x00</div>
                            </div>
                        </div>
                    </div>
                    
                    <div>
                        <h3 class="font-medium text-gray-700 mb-2 border-b pb-1">处理后的数据</h3>
                        <div class="space-y-3 text-sm">
                            <div class="p-2 bg-gray-50 rounded">
                                <div class="text-gray-600">gyro->gyroX = (int16_t)((data[0] << 8) | data[1])</div>
                                <div class="mt-1 font-medium">= 0x3CAB = <span id="gyroXValue">15531</span></div>
                            </div>
                            <div class="p-2 bg-gray-50 rounded">
                                <div class="text-gray-600">gyro->gyroY = (int16_t)((data[2] << 8) | data[3])</div>
                                <div class="mt-1 font-medium">= 0x1278 = <span id="gyroYValue">4728</span></div>
                            </div>
                            <div class="p-2 bg-gray-50 rounded">
                                <div class="text-gray-600">gyro->gyroZ = (int16_t)((data[4] << 8) | data[5])</div>
                                <div class="mt-1 font-medium">= 0x56F2 = <span id="gyroZValue">22258</span></div>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
        </div>
        
        <!-- 日志区域 -->
        <section class="mt-8 bg-white rounded-lg shadow-md p-6">
            <h2 class="text-xl font-semibold mb-4 text-dark flex items-center">
                <i class="fa fa-terminal text-gray-600 mr-2"></i>执行日志
            </h2>
            <div id="logArea" class="bg-gray-50 h-40 overflow-y-auto p-4 rounded border text-sm font-mono">
                <div class="text-gray-500">等待演示开始...</div>
            </div>
        </section>
    </main>

    <script>
        // 页面元素
        const startDemoBtn = document.getElementById('startDemoBtn');
        const mpuRegisters = document.querySelectorAll('.mpu-register');
        const arrayItems = document.querySelectorAll('.array-item');
        const dataFlow = document.querySelector('.data-flow');
        const transferSteps = document.getElementById('transferSteps');
        const logArea = document.getElementById('logArea');
        
        // 寄存器数据
        const registerData = [
            '0x3C', '0xAB', '0x12', '0x78', '0x56', '0xF2'
        ];
        
        // 日志输出
        function log(message) {
            const logEntry = document.createElement('div');
            logEntry.className = 'mb-1';
            logEntry.innerHTML = `[${new Date().toLocaleTimeString().split(' ')[0]}] ${message}`;
            logArea.appendChild(logEntry);
            logArea.scrollTop = logArea.scrollHeight;
        }
        
        // 演示流程
        async function startDemo() {
            // 禁用按钮防止重复点击
            startDemoBtn.disabled = true;
            startDemoBtn.classList.add('opacity-70', 'cursor-not-allowed');
            
            // 重置状态
            resetDemo();
            log("开始演示数据读取过程...");
            
            // 步骤1: 调用Inf_MPU6050_ReadGyro函数
            transferSteps.textContent = "调用 Inf_MPU6050_ReadGyro 函数";
            log("调用 Inf_MPU6050_ReadGyro(gyro)");
            await new Promise(resolve => setTimeout(resolve, 1500));
            
            // 步骤2: 内部创建data数组
            transferSteps.textContent = "创建 data[6] 数组";
            log("在函数内部创建 uint8_t data[6] = {0}");
            await new Promise(resolve => setTimeout(resolve, 1500));
            
            // 步骤3: 调用读取寄存器函数
            transferSteps.textContent = "调用 Inf_MPU6050_ReadRegs 函数";
            log("调用 Inf_MPU6050_ReadRegs(MPU_GYRO_XOUTH_REG, data, 6)");
            await new Promise(resolve => setTimeout(resolve, 1500));
            
            // 步骤4: 调用HAL库函数
            transferSteps.textContent = "调用 HAL_I2C_Mem_Read 函数";
            log("调用 HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR_R, 0x43, I2C_MEMADD_SIZE_8BIT, data, 6, 2000)");
            await new Promise(resolve => setTimeout(resolve, 1500));
            
            // 步骤5: 开始I2C通信
            transferSteps.textContent = "通过I2C读取数据";
            dataFlow.classList.remove('hidden');
            log("开始通过I2C总线读取数据...");
            await new Promise(resolve => setTimeout(resolve, 1000));
            
            // 逐个读取寄存器并填充数组
            for (let i = 0; i < 6; i++) {
                // 高亮当前寄存器
                mpuRegisters.forEach(reg => reg.classList.remove('bg-primary', 'text-white'));
                mpuRegisters[i].classList.add('bg-primary', 'text-white');
                
                // 高亮数组当前位置
                arrayItems.forEach(item => item.classList.remove('array-item-active'));
                arrayItems[i].classList.add('array-item-active');
                
                // 更新数组值
                arrayItems[i].querySelector('.font-medium').textContent = registerData[i];
                
                // 日志
                const regName = mpuRegisters[i].querySelector('.font-medium').textContent;
                const regAddr = mpuRegisters[i].dataset.reg;
                log(`读取寄存器 ${regName} (${regAddr}) -> 存储到 data[${i}] = ${registerData[i]}`);
                
                transferSteps.textContent = `读取 ${regName} 到 data[${i}]`;
                await new Promise(resolve => setTimeout(resolve, 1200));
            }
            
            // 步骤6: 函数返回，数组已填充
            dataFlow.classList.add('hidden');
            transferSteps.textContent = "数据读取完成";
            log("HAL_I2C_Mem_Read 函数执行完成，data数组已填充");
            await new Promise(resolve => setTimeout(resolve, 1500));
            
            // 步骤7: 处理数据
            transferSteps.textContent = "处理数据为16位值";
            log("将高低位数据组合为16位有符号整数");
            log(`gyro->gyroX = (int16_t)((data[0] << 8) | data[1]) = 0x3CAB = 15531`);
            log(`gyro->gyroY = (int16_t)((data[2] << 8) | data[3]) = 0x1278 = 4728`);
            log(`gyro->gyroZ = (int16_t)((data[4] << 8) | data[5]) = 0x56F2 = 22258`);
            
            await new Promise(resolve => setTimeout(resolve, 2000));
            
            // 演示结束
            transferSteps.textContent = "演示完成";
            log("数据读取和处理完成");
            startDemoBtn.disabled = false;
            startDemoBtn.classList.remove('opacity-70', 'cursor-not-allowed');
        }
        
        // 重置演示
        function resetDemo() {
            // 重置寄存器高亮
            mpuRegisters.forEach(reg => reg.classList.remove('bg-primary', 'text-white'));
            
            // 重置数组
            arrayItems.forEach((item, index) => {
                item.classList.remove('array-item-active');
                if (index >= 0) {
                    item.querySelector('.font-medium').textContent = '0x00';
                }
            });
            
            // 隐藏数据流
            dataFlow.classList.add('hidden');
            
            // 清空日志
            logArea.innerHTML = '<div class="text-gray-500">演示开始...</div>';
        }
        
        // 事件监听
        startDemoBtn.addEventListener('click', startDemo);
    </script>
</body>
</html>
